<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <p>{{globalCount}}</p>
      <p>{{name}}</p>
      <p>count1:{{count1}}</p>
      <p>doubleCount1:{{doubleCount1}}</p>
      <p>count2:{{count2}}</p>
      <p>doubleCount2:{{doubleCount2}}</p>
      <button @click="increase">+</button>
      <button @click="increaseAsync">increaseAsync</button>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
    <script src="https://unpkg.com/vuex@3.1.3/dist/vuex.js"></script>
    <script>
      const counter1 = {
        //给模块添加一个属性，命名空间，一旦为true后，当模块注册后，getter actions mutations 都会带有命名空间的前缀
        namespaced: true,
        state: { count: 1 }, //存放本模块中的局部状态
        mutations: {
          //存放本模块内的局部变更函数,访问的时候可以认为是全局的
          increase(state) {
            //mutation方法中接收的第一个参数是模块内的局部状态
            state.count++;
          },
          decrease(state) {
            //mutation方法中接收的第一个参数是模块内的局部状态
            state.count--;
          },
        },
        getters: {
          //存放本模块内的局部getters
          doubleCount1(state, getters, rootState, rootGetters) {
            //getters方法中接收的第一个参数是模块内的局部状态
            //1.局部状态 2.局部getters 3 全局状态 rootState 4.rootGetter 全局Getters
            return state.count * 2;
          },
        },
        actions: {
          increaseAsync(context) {
            //context=store
            //2个方法  commit提交mutation dispatch派发action ，它们在默认情况下都派发给自己模块的
            //4个属性 state rootState getters rootGetters
            setTimeout(() => {
              context.commit("increase");
              // unknown local mutation type: changeName, global type: counter1/changeName
              // 如果想在模块内提交全局命名空间下的mutation的时候，需要添加选项{root:true}
              //context.commit('changeName',{name:'xxx'},{root:true});
              //unknown local action type: decreaseAsync, global type: counter1/decreaseAsync
              context.dispatch("decreaseAsync");
            }, 1000);
          },
          //可以把此action注册成一个全局命名空间下的action
          //如果action没有设置为全局，派发它有两种方式 1，在模块内dispatch("decreaseAsync");
          //2.是在全局dispatch("counter1/decreaseAsync");

          //如果设置为root:true，那就不属于模块内的部局部action，属于全局空间了
          //在模块内就无法派发，因为如果在模块内派发的话一定会加命名空间的前缀
          //只能在全局派发，而且不需要加前缀.但是修改的还是模块内的状态
          decreaseAsync: {
            root: true,
            handler(context) {
              setTimeout(() => {
                context.commit("decrease");
              }, 1000);
            },
          },
        },
      };
      const counter2 = {
        namespaced: true,
        state: { count: 1 },
        mutations: {
          increase(state) {
            //mutation方法中接收的第一个参数是模块内的局部状态
            state.count++;
          },
        },
        getters: {
          doubleCount2(state) {
            return state.count * 2;
          },
        },
        actions: {
          increaseAsync(context) {
            //context=store
            setTimeout(() => {
              //在同一个模块内部，调用自己的mutation,不需要添加模块名的前缀
              context.commit("increase");
            }, 1000);
          },
        },
      };
      const store = new Vuex.Store({
        state: { name: "zhu", count: 100 }, //这个叫全局命名空间
        mutations: {
          ///全局命名空间下的mutation
          changeName(state, payload) {
            state.name = payload.name;
          },
          decrease(state, payload) {
            state.count--;
          },
        },
        modules: {
          //放定义多个模块，这些模块会合并在一起
          counter1, //模块名叫counter1，此名称会决定合并后的状态的属性名
          counter2, //第2个模块叫counter2
        },
      });
      var vm = new Vue({
        el: "#app",
        store,
        computed: {
          count1() {
            //不同的模块状态是分开的，要想获取某个模块的状态，需要通过模块名来获取
            return this.$store.state.counter1.count;
          },
          count2() {
            return this.$store.state.counter2.count;
          },
          doubleCount1() {
            //所有的模块的getters是合并在一起了。不需要通过模块名来访问
            return this.$store.getters["counter1/doubleCount1"];
          },
          doubleCount2() {
            return this.$store.getters["counter2/doubleCount2"];
          },
          name() {
            return this.$store.state.name;
          },
          globalCount() {
            return this.$store.state.count;
          },
        },
        methods: {
          increase() {
            //在提交变更的时候不需要添加模块名，直接提交mutation的名字就可以了
            //这样的话可以让多个模块同时响应一个提交commit
            //this.$store.commit('increase');
            this.$store.commit("counter1/increase");
            this.$store.commit("counter2/increase");
          },
          increaseAsync() {
            this.$store.dispatch("counter1/increaseAsync");
            this.$store.dispatch("counter2/increaseAsync");
          },
        },
      });
      //console.log(store.state);//rootState = {counter1:{count:1},counter2:{count:1}}
    </script>
  </body>
</html>
